import { DeleteOutlined } from '@ant-design/icons-vue';
import mitt from 'mitt';
const event = mitt();
export type Logic<T = any> = {
  type?: 'complex' | 'simple' | 'action';
  logic_type?: 'or' | 'and';
  children?: Logic<T>[];
  add?: boolean;
  remove?: boolean;
} & T;

type props = {
  condition_id?: string;
  name?: string;
};

const Item = defineComponent({
  props: {
    item: {
      type: Object as PropType<Logic<props>>,
      required: true,
    },
    index: {
      type: Number,
      default: 0,
    },
    parent: {
      type: Object as PropType<HTMLElement>,
    },
    node: {
      type: Object as PropType<Logic<props>>,
    },
    list: {
      type: Array as PropType<
        {
          name: any;
          condition_id: string;
          disabled: boolean;
        }[]
      >,
      default: () => [],
    },
    canChoose: {
      type: Boolean,
    },
  },
  setup(props) {
    const { item, index, node, list, canChoose } = toRefs(props);
    const pRef = ref();

    const calcStyle = () => {
      const _parent = props.parent;
      const _child = pRef.value;
      const lineWidth = window.devicePixelRatio * 1;
      if (item.value.type == 'action') {
        if (!item.value.add) return {};
      }
      if (_parent && _child) {
        const pRect = _parent.getBoundingClientRect();
        const cRect = _child.getBoundingClientRect();
        const width = cRect.x - pRect.x;
        let height = cRect.y - pRect.y;
        let top;
        const style = {
          width: width + 'px',
          height: height + 'px',
          left: `-${width - pRect.width / 2}px`,
        };
        if (height < 0) {
          height = -height;
          top = cRect.height / 2;
          Object.assign(style, {
            borderLeft: `${lineWidth}px solid #eee`,
            borderTop: `${lineWidth}px solid #eee`,
            top: top + 'px',
            height: height + 'px',
          });
        } else {
          top = -height + cRect.height / 2;
          Object.assign(style, {
            borderLeft: `${lineWidth}px solid #eee`,
            borderBottom: `${lineWidth}px solid #eee`,
            top: top + 'px',
            height: height + 'px',
          });
        }
        return style;
      }
      return {};
    };

    const style = ref({});
    onMounted(() => {
      nextTick(() => {
        style.value = calcStyle();
      });
      event.on('change', () => {
        nextTick(() => {
          style.value = calcStyle();
        });
      });
    });

    // 添加
    const add = () => {
      if (node.value) {
        if (!node.value.children) {
          node.value.children = [];
        }
        node.value.children.push({ type: 'simple', condition_id: undefined });
        event.emit('change');
      }
    };

    // 添加组
    const addGroup = () => {
      if (node.value) {
        if (!node.value.children) {
          node.value.children = [];
        }
        node.value.children.push({
          type: 'complex',
          logic_type: 'or',
          children: [],
        });
        event.emit('change');
      }
    };

    // 删除
    const remove = (item: Logic<props>) => {
      if (node.value?.children) {
        node.value.children = node.value.children.filter(
          child => child != item
        );
      }
      event.emit('change');
    };

    // 删除组
    const removeGroup = () => {
      event.emit('removeGroup', node.value);
    };

    const genList = () => {
      let list: Logic<props>[] = [];
      if (item.value.children?.length) {
        list = list.concat(item.value.children!);
      }
      if (canChoose.value) {
        list = list.concat({
          type: 'action',
          add: true,
          remove: item.value.children?.length == 0,
        });
      } else {
        list = list.concat({
          type: 'action',
          remove: item.value.children?.length == 0,
        });
      }
      return list;
    };

    return () => (
      <div class="flex items-center relative my-10px">
        <div>
          {item.value.type == 'simple' ? (
            <div class="relative flex" ref={pRef}>
              <div class="absolute" style={style.value}></div>
              <a-select
                placeholder="请选择"
                v-model:value={item.value.condition_id}
                class="w-300px mr-10px"
                allowClear
              >
                {list.value.map(record => {
                  return (
                    <a-select-option
                      key={record.condition_id}
                      value={record.condition_id}
                      disabled={record.disabled}
                    >
                      {record.name}
                    </a-select-option>
                  );
                })}
              </a-select>
              <a-button
                type="link"
                icon={<DeleteOutlined />}
                onClick={() => remove(item.value)}
              ></a-button>
            </div>
          ) : item.value.type == 'action' ? (
            <div class="relative" ref={pRef}>
              <div class="absolute" style={style.value}></div>
              <a-space>
                {item.value.add && (
                  <a-button type="primary" onClick={add}>
                    添加
                  </a-button>
                )}
                {index.value <= 1 && item.value.add && (
                  <>
                    <a-button type="primary" onClick={addGroup}>
                      添加组
                    </a-button>
                  </>
                )}
                {item.value.remove && index.value > 1 && (
                  <a-button type="primary" onClick={removeGroup}>
                    删除
                  </a-button>
                )}
              </a-space>
            </div>
          ) : (
            <div class="w-70px mr-50px relative" ref={pRef}>
              {index.value > 0 && (
                <div class="absolute" style={style.value}></div>
              )}
              <a-select
                v-model:value={item.value.logic_type}
                class="w-full relative z-1"
              >
                <a-select-option value="or">或</a-select-option>
                <a-select-option value="and">且</a-select-option>
              </a-select>
            </div>
          )}
        </div>
        <div>
          {item.value.children
            ? genList().map(child => {
                return (
                  <Item
                    item={child}
                    index={index.value + 1}
                    parent={pRef.value}
                    node={item.value}
                    list={list.value}
                    canChoose={canChoose.value}
                  />
                );
              })
            : null}
        </div>
      </div>
    );
  },
});

export default defineComponent({
  props: ['data', 'list', 'max'],
  setup(props) {
    const parent = ref();

    const canChoose = computed(
      () =>
        props.list.some(item => !item.disabled) && props.max < props.list.length
    );

    event.on('removeGroup', node => {
      props.data.children = props.data.children.filter(item => item != node);
      event.emit('change');
    });

    onBeforeUnmount(() => {
      event.all.clear();
    });

    return () => (
      <div class="w-70px">
        <Item
          item={props.data}
          index={0}
          parent={parent.value}
          list={props.list}
          canChoose={canChoose.value}
        ></Item>
      </div>
    );
  },
});
